﻿using System;
using System.Collections.Generic;
using System.IO;
using ooWii.Collections;

namespace ooWii.Security
{
	public class Tmd
	{
		#region Tmd

		IList<Content> content = new List<Content>();
		Signature signature;
		string issuer;
		byte[] bytes;

		public static Tmd Create( Stream stream, SHA1Engine sha1Engine )
		{
			Tmd tmd = new Tmd();

			tmd.signature = Signature.Create( stream );

			byte[] buffer = new byte[ stream.Length - stream.Position ];

			if( stream.Read( buffer, 0, buffer.Length ) != buffer.Length )
			{
				throw new WiiException( "Cannot read title meta data" );
			}

			tmd.bytes = buffer;
			tmd.issuer = WiiBuffer.GetString( buffer, 0, 0x40 );

			UInt64 ios = WiiBuffer.GetUInt64( buffer, 0x44 );
			UInt16 nbr_cont = WiiBuffer.GetUInt16( buffer, 0x9e );

			for( int i = 0; i < nbr_cont; i++ )
			{
				int contentOffset = 0xa4 + ( i * 36 );

				UInt32 contentId = WiiBuffer.GetUInt32( buffer, contentOffset );
				UInt16 index = WiiBuffer.GetUInt16( buffer, contentOffset + 4 );
				UInt16 type = WiiBuffer.GetUInt16( buffer, contentOffset + 6 );
				UInt64 contentSize = WiiBuffer.GetUInt64( buffer, contentOffset + 8 );
				byte[] hash = WiiBuffer.GetBytes( buffer, contentOffset + 16, 20 );

				tmd.content.Add( new Content( contentId, index, type, contentSize, hash, sha1Engine ) );
			}

			return tmd;
		}

		Tmd()
		{
		}

		public IList<Content> Content
		{
			get
			{
				return content;
			}
		}

		public void VerifySignature( CertificateChain certificateChain )
		{
			PublicKey publicKey;
			if( !certificateChain.TryGetValue( issuer, out publicKey ) )
			{
				throw new WiiException( "TMD issuer not found" );
			}

			if( !publicKey.VerifySignature( bytes, signature ) )
			{
				throw new WiiException( "TMD signature check failed" );
			}
		}

		#endregion
	}
}
